local blaze = require "blaze"
local app = require "app"
local gamelib = require "club.threecard.gamelib"
local slotlib = require "club.threecard.slotlib"
local game = app.game.running
local log = blaze.logging.get("Hud")

local M = gamelib.ui.element()

local default_res = "club.threecard.slotlib/ui/common.b:SlotHud"

local function update_seats(self, state)
    local me = blaze.kbe.player()
    if not me or not me.seat or me.seat.no == 0 then
        return
    end
    local my_no = me.seat.no
    for i=1, 4 do
        local no = my_no + i
        if no > 5 then
            no = no - 5
        end
        local seat = state.seats[no]
        local local_no = slotlib.seat.to_local(no)
        if local_no > 0 then
            if seat then
                self.seats[local_no]:set_player(seat.owner)
            else
                self.seats[local_no]:clear_player()
            end
        else
            log.warn(string.format("座位号异常：server=%s local=%s no=%s dump=%s", my_no, local_no, no, slotlib.seat.dump()))
        end
    end
end

M.store_watchers = {
    player = {
        ["$"] = blaze.noop,

        ["等级变更"] = function(self, store, state, args)
            game.store.machine.refilter_bet_amounts()
        end
    },
    room = {
        ["$"] = function(self, store, state, args)
            update_seats(self, state)
        end,

        ["玩家坐下"] = function(self, store, state, args)
            update_seats(self, state)
        end,

        ["玩家站起"] = function(self, store, state, args)
            update_seats(self, state)
        end,

        ["玩家换座"] = function(self, store, state, args)
            update_seats(self, state)
        end
    },
    gameplay = {
        ["$"] = blaze.noop,
        
        ["玩家获得赔付"] = function(self, store, state, args)
            local player = args.player
            local payout = args.payout
            local local_no = slotlib.seat.to_local(player.seat.no)
            if not local_no then
                return
            end
            local seat = self.seats[local_no]
            if not seat then
                return
            end
            seat:play_payout_fx(payout)
        end
    },
    chat = {
        ["$"] = blaze.noop,

        ["收到聊天消息"] = function(self, store, state, args)
            local player = args.sender
            if not player.seat then
                return
            end
            local local_no = slotlib.seat.to_local(player.seat.no)
            if local_no == 0 then
                self.player_info.chatter:chat(args)
                return
            end
            local seat = self.seats[local_no]
            if not seat then
                return
            end
            seat.chatter:chat(args)
        end
    }
}

function M:ctor(ingame, res)
    -- TODO: 理论上不应该耦合这些参数
    self.ingame = ingame

    self.res = default_res or res
    self.last_win = slotlib.require("widget.LastWin").new()
    self.player_info = gamelib.require("widget.player_info").new()
    self.online_bonus_anim = require("ui.Widget.chip_anim").new()
    self.online_bonus = require("club.threecard.gamelib.widgets.OnlineBonus").new()
    self.online_bonus.on_collected = function()
        local src = self.online_bonus:get_chip_transform()
        local dst = self.player_info:get_chip_transform()
        self.online_bonus_anim:play(src, dst, 4)
        app.audio.post("online_bonus:collected")
    end
    self.bet_viser = slotlib.require("widget.BetViser").new()
    self.spin_button = slotlib.require("widget.SpinButton").new(ingame.context, ingame.systems)
    self.freespin = slotlib.require ("widget.FreeSpin").new(ingame.context, ingame.systems)
    self.seats = {}
    local Seat = slotlib.require("widget.Seat")
    local chat = gamelib.chat
    for i=1, 2 do
        local seat = Seat.new()
        seat.chatter:set_chat_facing(chat.FACING_RIGHT)
        table.insert(self.seats, seat)
    end
    for i=3, 4 do
        local seat = Seat.new()
        seat.chatter:set_chat_facing(chat.FACING_LEFT)
        table.insert(self.seats, seat)
    end
end

function M:on_load()
    self:super("on_load")
    self.online_bonus:load()
    for _, seat in ipairs(self.seats) do
        seat:load()
    end
    self.last_win:load()
end

function M:on_injected(bind)
    bind("gameobject.element", self.last_win_obj, self.last_win)
    bind("gameobject.element", self.bet_viser_obj, self.bet_viser)
    bind("gameobject.element", self.spin_btn_obj, self.spin_button)
    bind("gameobject.element", self.player_info_obj, self.player_info)
    bind("gameobject.element", self.freespin_obj, self.freespin)
    bind("button.click", self.back_btn, self.on_backward)
    bind("shortcut.escape", self.back_btn.gameObject, self.on_backward)
    bind("gameobject.element", self.seat1_obj, self.seats[1])
    bind("gameobject.element", self.seat2_obj, self.seats[2])
    bind("gameobject.element", self.seat3_obj, self.seats[3])
    bind("gameobject.element", self.seat4_obj, self.seats[4])
    bind("gameobject.element", self.online_bonus_obj, self.online_bonus)
    gamelib.utility.button_style.highlight_scale(self.back_btn)
end

function M:on_backward()
    self.ingame.systems:tear_down()
    self.ingame.machine:shutdown()
    game.game_scene.leave()
end

function M:on_free()
    self.animator:Play("freespin_clip", 0, 0)
end

function M:on_over_free()
    self.animator:Play("freespin_over_clip", 0, 0)
end

function M:on_release()
    self:super("on_release")
    self.player_info:release()
    self.online_bonus:release()
    self.online_bonus_anim:release()
    for _, seat in ipairs(self.seats) do
        seat:release()
    end
    self.last_win:release()
end

return M